package com.team.teamuserservice.service.impl;

import com.team.teamuserservice.config.RedissonConfig;
import com.team.teamuserservice.entity.po.BizRescueTask;
import com.team.teamuserservice.mapper.BizRescueTaskMapper;
import com.team.teamuserservice.service.IBizRescueTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.team.teamuserservice.websocket.service.MerchantMessageHandler;
import com.team.teamuserservice.websocket.service.MessageHandler;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 救援任务表 服务实现类
 * </p>
 *
 * @author cxs
 * @since 2025-07-10
 */
@Service
public class BizRescueTaskServiceImpl extends ServiceImpl<BizRescueTaskMapper, BizRescueTask> implements IBizRescueTaskService {

    private static final String LOCK = "lock:rescue:";

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private MerchantMessageHandler messageHandler;


    @Override
    public Boolean acceptRescue(Long userId, Long merchantId) throws InterruptedException {


        //对于每个抢单为了防止意外一定先查订单的状态
        List<BizRescueTask> list = lambdaQuery()
                .eq(BizRescueTask::getUserId, userId)
                .eq(BizRescueTask::getStatus, "0")//待接单
                .list();
        //如果查不到待接单的订单 , 直接返回失败
        if (list.isEmpty()) {
            return false;
        }
        //代表现在可能可以抢单 , 尝试获取redisson锁
        RLock lock = redissonClient.getLock(LOCK + userId);
        //尝试获取redisson锁 , 只设置1秒的重试防止出现意外 , 不设置获取锁的时间 , 利用看门狗机制自动续锁
        boolean success = lock.tryLock(1, TimeUnit.SECONDS);
        //抢单失败 , 滚蛋
        if (!success){
            return false;
        }
        //抢单成功 , 在持有锁的情况下更新订单的状态 , 防止比如我异步更新订单状态 , 但是锁释放了订单还没修改完 , 导致又有人获取到了锁
        //更新的时候也要使用乐观锁的机制 , 确保订单的状态还是未结单
        boolean update = lambdaUpdate()
                .eq(BizRescueTask::getStatus, "0")//还是未接单 , 数据库update具有排它锁 , 完美符合乐观锁
                .set(BizRescueTask::getStatus, "1")//接单中
                .set(BizRescueTask::getShopId, merchantId)
                .set(BizRescueTask::getUpdateTime, LocalDateTime.now())
                .eq(BizRescueTask::getId, list.get(list.size() - 1).getId())
                .update();

        //代表抢单成功 , 但是订单状态被其他操作抢走了 , 同样认为抢单
        if (! update){
            return false;
        }

        //释放锁
        lock.unlock();
        //代表这个商家抢单成功了 , 在前端尝试发送ws消息给对应的用户
        return true;

    }
}
